package com.reider.log4AS3.utils
{
	
	import flash.utils.describeType;
	import flash.utils.getQualifiedClassName;
	
	public class ObjectTracer
	{	
		public static function objectToHierearchy(obj:Object, addedObjs:Array, name:String=""):Object
		{
			if(isPrimitive(obj)){
				var pimObj:Object = new Object()
				pimObj.name = name
				
				if(obj is String){
					pimObj.value = "\""+obj+"\""
				}else{
					pimObj.value = String(obj)
				}
				
				return pimObj
				
			}else if(addedObjs.indexOf(obj)+1){
				
				return {name:name, value:"::recursive::"}
				
			}else{	
				var arr:Array = new Array()
				var keys:Array = getPublicKeys(obj)
				var paramValue:*
				var value:*
				var key:String
				
				addedObjs.push(obj)
				for(key in obj){
					keys.push(key)
				}
				
				for each(key in keys){
					try{
						paramValue = obj[key]
						value = objectToHierearchy(paramValue, addedObjs, key)
						if(value is Array){
							arr.push({name: key, value:"@"+getQualifiedClassName(paramValue), children:value})
						}else{
							arr.push(value)
						}	
					}catch(error:Error){}
				}
				return arr
			}
		}
		
		public static function getPublicKeys(obj:Object):Array
		{	
			var keys:Array = new Array()	
			var description:XML = describeType(obj)
			var accessors:XMLList = description.accessor
			var variables:XMLList = description.variable
			
			getXmlKeys(accessors, keys)
			getXmlKeys(variables, keys)
			
			return keys
			
		}
		
		private static function getXmlKeys(list:XMLList, keys:Array):void
		{
			for each(var node:XML in list){
				var name:String = String(node.@name)
				if(keys.indexOf(name) == -1){
					keys.push(name)
				}
			}
		}
		
		public static function isPrimitive(obj:Object):Boolean
		{
			switch(getQualifiedClassName(obj)){
				case "int":
				case "uint":
				case "Number":
				case "Boolean":
				case "String":
					return true
				break
				default:
					if(obj is Object){
						return false
					}else{
						return true
					}
			}
		}

	}
}